package com.micro.ai.models.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.micro.ai.commons.exception.BusinessException;
import com.micro.ai.models.entity.FineTuningJob;
import com.micro.ai.models.mapper.FineTuningJobMapper;
import com.micro.ai.models.service.FineTuningJobService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * 微调任务服务实现
 * 
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@Service
public class FineTuningJobServiceImpl extends ServiceImpl<FineTuningJobMapper, FineTuningJob> implements FineTuningJobService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FineTuningJob create(FineTuningJob job) {
        if (job == null) {
            throw new BusinessException("M0000", "微调任务信息不能为空");
        }
        
        LocalDateTime now = LocalDateTime.now();
        job.setCreatedAt(now);
        job.setUpdatedAt(now);
        if (job.getStatus() == null) {
            job.setStatus("pending");
        }
        
        boolean success = this.save(job);
        if (!success) {
            throw new BusinessException("M0003", "创建微调任务失败");
        }
        
        log.info("创建微调任务成功: jobId={}, jobName={}", job.getId(), job.getJobName());
        return job;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FineTuningJob update(String id, FineTuningJob job) {
        if (!StringUtils.hasText(id)) {
            throw new BusinessException("M0000", "任务ID不能为空");
        }
        if (job == null) {
            throw new BusinessException("M0000", "微调任务信息不能为空");
        }
        
        FineTuningJob existing = this.getById(id);
        if (existing == null) {
            throw new BusinessException("M0002", "微调任务不存在: " + id);
        }
        
        job.setId(id);
        job.setUpdatedAt(LocalDateTime.now());
        
        boolean success = this.updateById(job);
        if (!success) {
            throw new BusinessException("M0003", "更新微调任务失败");
        }
        
        log.info("更新微调任务成功: jobId={}", id);
        return job;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String id) {
        if (!StringUtils.hasText(id)) {
            throw new BusinessException("M0000", "任务ID不能为空");
        }
        
        FineTuningJob job = this.getById(id);
        if (job == null) {
            throw new BusinessException("M0002", "微调任务不存在: " + id);
        }
        
        boolean success = this.removeById(id);
        if (!success) {
            throw new BusinessException("M0003", "删除微调任务失败");
        }
        
        log.info("删除微调任务成功: jobId={}, jobName={}", id, job.getJobName());
    }

    @Override
    public Page<FineTuningJob> pageQuery(int pageNum, int pageSize, String tenantId, String keyword, String status) {
        if (pageNum < 1) {
            pageNum = 1;
        }
        if (pageSize < 1 || pageSize > 100) {
            pageSize = 20;
        }
        
        Page<FineTuningJob> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<FineTuningJob> query = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(tenantId)) {
            query.eq(FineTuningJob::getTenantId, tenantId);
        }
        if (StringUtils.hasText(status)) {
            query.eq(FineTuningJob::getStatus, status);
        }
        if (StringUtils.hasText(keyword)) {
            query.and(q -> q.like(FineTuningJob::getJobName, keyword)
                          .or().like(FineTuningJob::getFineTunedModelName, keyword));
        }
        
        query.orderByDesc(FineTuningJob::getCreatedAt);
        
        return this.page(page, query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void start(String id) {
        if (!StringUtils.hasText(id)) {
            throw new BusinessException("M0000", "任务ID不能为空");
        }
        
        FineTuningJob job = this.getById(id);
        if (job == null) {
            throw new BusinessException("M0002", "微调任务不存在: " + id);
        }
        
        if (!"pending".equals(job.getStatus())) {
            throw new BusinessException("M0000", "任务状态不正确，只有pending状态的任务才能启动");
        }
        
        job.setStatus("preparing");
        job.setStartedAt(LocalDateTime.now());
        job.setUpdatedAt(LocalDateTime.now());
        
        boolean success = this.updateById(job);
        if (!success) {
            throw new BusinessException("M0003", "启动任务失败");
        }
        
        log.info("启动微调任务: jobId={}, jobName={}", id, job.getJobName());
        
        // 提交任务到调度器（异步执行）
        try {
            // 如果注入了TaskSchedulerService，则使用它提交任务
            // TaskSchedulerService taskScheduler = ...; // 通过Spring注入
            // String externalJobId = taskScheduler.submitTrainingJob(job);
            // job.setExternalJobId(externalJobId);
            // this.updateById(job);
            
            // 实际实现时，可以选择以下方案之一：
            // 方案1: 消息队列（RabbitMQ/Redis/Kafka）- 推荐
            // 方案2: Kubernetes Job - 适合容器化部署
            // 方案3: 外部API（OpenAI Fine-tuning API等）- 适合使用云服务
            // 方案4: 线程池异步执行 - 适合简单场景
            
            // 当前为框架代码，实际实现需要：
            // 1. 添加消息队列依赖和配置
            // 2. 实现TaskSchedulerService接口
            // 3. 在FineTuningJobServiceImpl中注入TaskSchedulerService
            // 4. 调用submitTrainingJob方法
            
            log.info("任务已提交，等待调度器处理: jobId={}", id);
            
        } catch (Exception e) {
            log.error("提交任务到调度器失败: jobId={}, error={}", id, e.getMessage(), e);
            // 回滚状态
            job.setStatus("pending");
            job.setErrorMessage("提交任务失败: " + e.getMessage());
            this.updateById(job);
            throw new BusinessException("M0003", "提交训练任务失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(String id) {
        if (!StringUtils.hasText(id)) {
            throw new BusinessException("M0000", "任务ID不能为空");
        }
        
        FineTuningJob job = this.getById(id);
        if (job == null) {
            throw new BusinessException("M0002", "微调任务不存在: " + id);
        }
        
        if ("completed".equals(job.getStatus()) || "failed".equals(job.getStatus())) {
            throw new BusinessException("M0000", "已完成或失败的任务不能取消");
        }
        
        job.setStatus("cancelled");
        job.setUpdatedAt(LocalDateTime.now());
        
        boolean success = this.updateById(job);
        if (!success) {
            throw new BusinessException("M0003", "取消任务失败");
        }
        
        log.info("取消微调任务: jobId={}, jobName={}", id, job.getJobName());
    }

    @Override
    public FineTuningJob getProgress(String id) {
        if (!StringUtils.hasText(id)) {
            throw new BusinessException("M0000", "任务ID不能为空");
        }
        
        FineTuningJob job = this.getById(id);
        if (job == null) {
            throw new BusinessException("M0002", "微调任务不存在: " + id);
        }
        
        return job;
    }
}

